#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "./lcd/bsp_ili9341_lcd.h"
#include "usart.h"
#include "key.h"
#include "stdio.h"

#define START_TASK_PRIO		1
#define START_STK_SIZE 		128  
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);

#define LED0_TASK_PRIO		2
#define LED0_STK_SIZE 		50
TaskHandle_t led0_task_handler;
void LED0_Task(void *pvParameters);


#define LCD_TASK_PRIO		4
#define LCD_STK_SIZE 	128
TaskHandle_t lcd_task_handler;
void LCD_Task(void *pvParameters);


#define KEY_TASK_PRIO		3
#define KEY_STK_SIZE 		512
TaskHandle_t key_task_handler;
void KEY_Task(void *pvParameters);


void Send_Info();
void SendSys_Task_Info();
	
char disbuff[20];
int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	KEY_Init();
	LED_Init();		        //初始化LED端口
	ILI9341_Init();//液晶初始化    
	LCD_SetColors(BLACK,WHITE);//设置白底黑字
	LCD_SetFont(&Font8x16);//设置字体大小
	ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);//清屏
  ILI9341_GramScan ( 6 );//设置显示模式
	USART_Config(115200);
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}
 
//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )LED0_Task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&led0_task_handler);   
    

    //创建KEY任务
    xTaskCreate((TaskFunction_t )KEY_Task,     
                (const char*    )"key_task",   
                (uint16_t       )KEY_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )KEY_TASK_PRIO,
                (TaskHandle_t*  )&key_task_handler);   
								
	  //创建LCD任务
    xTaskCreate((TaskFunction_t )LCD_Task,     
                (const char*    )"lcd_task",   
                (uint16_t       )LCD_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LCD_TASK_PRIO,
                (TaskHandle_t*  )&lcd_task_handler);
								
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED0任务函数 
void LED0_Task(void *pvParameters)
{
    while(1)
    {
		  LED_Color(LED_RED);
		  vTaskDelay(500);
		  LED_Color(LED_OFF);
		  vTaskDelay(500);
			//printf("TickCount:%d\n",xTaskGetTickCount());
    }
}   


int flag = 0;
void KEY_Task(void *pvParameters)
{
    while(1)
    {
			
				if(KEY_Scan()=='1')
				{
					flag = !flag;
					Send_Info();
					SendSys_Task_Info();
					//printf("Current_Task_Numer:%d\n",uxTaskGetNumberOfTasks());
					if(flag==1)
					{
						ILI9341_DispStringLine_EN(LINE(1),"LED_Suspend");
						vTaskSuspend(led0_task_handler);
					}
					else
					{
						ILI9341_DispStringLine_EN(LINE(1),"LED_Resume   ");
						vTaskResume(led0_task_handler);
					}
					
				}
        vTaskDelay(20);
    }
}

void LCD_Task(void *pvParameters)
{
	  int led_priority;
	  eTaskState led_task_state;

    while(1)
    {
			if(flag)
				ILI9341_DispStringLine_EN(LINE(1),"LED_Suspend");
			else
				ILI9341_DispStringLine_EN(LINE(1),"LED_Resume   ");
			
			led_priority = uxTaskPriorityGet(led0_task_handler);
			sprintf(disbuff,"LED_Pri:%d",led_priority);
			ILI9341_DispStringLine_EN(LINE(2),disbuff);
			
			led_task_state = eTaskGetState(led0_task_handler);
			sprintf(disbuff,"LED_State:%d",led_task_state);
			ILI9341_DispStringLine_EN(LINE(3),disbuff);
			
			sprintf(disbuff,"LED_Task_Name:%s",	pcTaskGetName(led0_task_handler));
			ILI9341_DispStringLine_EN(LINE(4),disbuff);

			sprintf(disbuff,"LED_StackHighWater:%3d",	uxTaskGetStackHighWaterMark(led0_task_handler));
			ILI9341_DispStringLine_EN(LINE(5),disbuff);
			
			vTaskDelay(100);
    }
}

void Send_Info()
{
	  TaskStatus_t led_status;
		vTaskGetInfo(led0_task_handler,&led_status,pdTRUE,0);
		printf("------------Get Task Info------------\r\n");
		printf("eCurrentState = %d\r\n",led_status.eCurrentState);
		printf("pcTaskName = %s\r\n",led_status.pcTaskName);
		printf("pxStackBase = %#x\r\n",(int)led_status.pxStackBase);
		printf("usStackHighWaterMark = %d\r\n",led_status.usStackHighWaterMark);
		printf("uxBasePriority = %ld\r\n",led_status.uxBasePriority);
		printf("uxCurrentPriority = %ld\r\n",led_status.uxCurrentPriority);
		printf("xTaskNumber = %ld\r\n",led_status.xTaskNumber);
		printf("xHandle = %#x\r\n",(void *)led_status.xHandle);
//			printf("QueryTask_Handler= %#x\r\n",(void *)led_status);
		printf("------------Get Task Info------------\r\n");
}

void SendSys_Task_Info()
{
	int i;
	TaskStatus_t arr[20];
	int arr_size = uxTaskGetNumberOfTasks();
	
	uxTaskGetSystemState(arr,arr_size,NULL);
	printf("TaskName\tPriority\tTaskNumber\t\tStackHighWater\n");
	for(i=0;i<arr_size;i++)
	{
		//通过串口打印出获取到的系统的有关信息 比如任务名称,
		//任务优先级和任务编号
		printf("%s\t%d\t%d\t\t%d\n",
		arr[i].pcTaskName,
		(int)arr[i].uxCurrentPriority,
		(int)arr[i].xTaskNumber,
			arr[i].usStackHighWaterMark);
	}
}
